
/*
* PROJECT: Alcyone  Kernel
* LICENSE: BSD Clause 3 
* PURPOSE: Cache Controller:: MDL Handler   
* NT KERNEL: 5.11.9360 
* COPYRIGHT: 2023-2029 Dibymartanda Samanta <>
*             
*/

#include <ntoskrnl.h>
#include "debug.h"
#include "cacheman.hpp"
#define NTDEBUG

extern "C"

// Internal Test Tools C:\Users\Dibya\source\repos\Hello\Debug\Hello.exe
// hello.sys must be loaded as a service before collecting logs and running tests. 

/* Move Later to header */
PEX_PUSH_LOCK  	VACB_SYS_LOCK; // To ensure thread safety 
constexpr MDL_READTYPE_DiskIoAttribution 0
constexpr optional_irp 0
constexpr MDL MAXIO_DISPATCH 76
constexpr NOPRIORITY 0 




VOID
NTAPI
CcMdlReadComplete2 (
    IN PFILE_OBJECT FileObject,
    IN PMDL MdlChain
)
{
	  PMDL MDLBuffer;
	  PMDL MDLNext; 
	 /* Check if MDL Chain is Valid */
	if (MdlChain)
	{
		do
		{
			MDLNext = MDLBuffer->Next;
			/*Unlock the memory pages associated with the MDL*/
			MmUnlockPages(MDLBuffer); 
			/*Free The MDL */
			IoFreeMdl(MDLBuffer); 
			/* Move to next MDL */ 
			MDLBuffer = MDLNext;
		} while (MDLNext); 
	}
}

CcMdlWriteComplete2(IN PFILE_OBJECT FileObject,
                    IN PLARGE_INTEGER FileOffset,
                    IN PMDL MdlChain)
{
PMDL Buffer = MdlChain; 
PMDL MDLNext = nullptr;
PMDL Buffer2 = nullptr; 
KIRQL CurrentIrql = null;

do
  {
    MDLNext = Buffer->Next;
    if (!(MdlChain->MdlFlags & 2) == 0) )
    {
      MmUnlockPages(Buffer);
     
    }
    if ( (FileObject->Flags & 16) != 0 )
    {
      MmFlushSection(Buffer->ByteCount, SharedCacheMap, &IoStatus, 1);
      if ( IoStatus.Status < 0 )
        Exception = IoStatus.Status;
    }
    else
    {
      CcSetDirtyInMask(SharedCacheMap, &FOffset, Buffer->ByteCount);
    }
    FOffset.QuadPart += Buffer->ByteCount;
    Buffer = MDLNext;
  }
  while ( MDLNext);
  Buffer2 = MdlChain;
  if (!(MdlChain->MdlFlags & 2) == 0))
  {
    CurrentIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
    CcDecrementOpenCount(SharedCacheMap);
    KeReleaseQueuedSpinLock(LockQueueMasterLock,CurrentIrql);
  }
  if (!NT_SUCCESS(Exception))                          
  {
    RtlRaiseStatus(FsRtlNormalizeNtstatus(Exception, WRITE_EXCEPTION));
  }
  do
  {
    MDLNext = Buffer2->Next;
    IoFreeMdl(Buffer2);
    Buffer2 = MDLNext;
  }
  while (MDLNext);
}








NTSTATUS VOID CcFreeVirtualAddress(PVACB Vacb)
{
   PSHARED_CACHE_MAP SharedCacheMap; 
   PKEVENT WaitOnActiveCount; 

  SharedCacheMap = Vacb->SharedCacheMap;
  
  
 BOOL Overlay_Status = const_cast<BOOL>( InterlockedDecrement(&static_cast< volatile LONG*>(&Vacb->Overlay)));
  if (!Overlay_Status)
  {
    WaitOnActiveCount = SharedCacheMap->WaitOnActiveCount;
    if ( WaitOnActiveCount )
      KeSetEvent(WaitOnActiveCount,NOPRIORITY, false);
  }
}










VOID
NTAPI
CcMdlReadComplete(IN PFILE_OBJECT FileObject,
                  IN PMDL MdlChain)
{
    PDEVICE_OBJECT RelatedDeviceObject = IoGetRelatedDeviceObject(FileObject);
    FAST_IO_DISPATCH FastIoDispatch = RelatedDeviceObject->DriverObject->FastIoDispatch;
	/* Start Faster MDL Operator if Suceeds , don't execute slower CcMdlReadComplete2*/
	BOOL MdlReadComplete_FLag =  (*PFAST_IO_MDL_READ_COMPLETE) ( PFILE_OBJECT FileObject,PMDL MdlChain,PDEVICE_OBJECT RelatedDeviceObject);
    
	if ( !FastIoDispatch|| FastIoDispatch->SizeOfFastIoDispatch <= MAXIO_DISPATCH|| (MdlReadComplete_FLag = FastIoDispatch->MdlReadComplete) == 0|| !MdlReadComplete_FLag )
   {
    CcMdlReadComplete2(0,MdlChain);
   }
}
	

VOID
NTAPI
CcMdlWriteAbort(IN PFILE_OBJECT FileObject,
                IN PMDL MdlChain)
{
	
	PMDL Buffer = MdlChain;
	PMDL Next = nullptr;
	KIRQL CurrentIrql = null;
  PSHARED_CACHE_MAP SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;

do
  {
    Next = Buffer->Next;
    if ((MdlChain->MdlFlags & 2) != 0 )
    MmUnlockPages(Buffer);
    IoFreeMdl(Buffer);
    Buffer = Next;
  }
  while ( Next );
  if ( (MdlChain->MdlFlags & 2) != 0 )
  {
     CurrentIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock);
    CcDecrementOpenCount(SharedCacheMap);
    KeReleaseQueuedSpinLock(LockQueueMasterLock, CurrentIrql);
  }
}

VOID
NTAPI
CcMdlWriteComplete(IN PFILE_OBJECT FileObject,
                   IN PLARGE_INTEGER FileOffset,
                   IN PMDL MdlChain)
{
	
	DEVICE_OBJECT RelatedDeviceObject = IoGetRelatedDeviceObject(FileObject);
    FAST_IO_DISPATCH FastIoDispatch = RelatedDeviceObject->DriverObject->FastIoDispatch;
	
	BOOL MdlWriteComplete_FLag = (*PFAST_IO_MDL_WRITE_COMPLETE) (PFILE_OBJECT FileObject,PLARGE_INTEGER FileOffset,PMDL MdlChain,PDEVICE_OBJECT RelatedDeviceObject);
		/* Start Faster MDL Operator if Suceeds , don't execute slower CcMdlReadComplete2*/
		
		
	if (!FastIoDispatch|| FastIoDispatch->SizeOfFastIoDispatch <= MAXIO_DISPATCH|| (MdlWriteComplete_FLag = FastIoDispatch->MdlWriteComplete) == 0||  !MdlWriteComplete_FLag)
  {
     CcMdlWriteComplete2(FileObject,FileOffset,MdlChain);
  }
}


VOID
NTAPI
CcPrepareMdlWrite(IN PFILE_OBJECT FileObject,
                  IN PLARGE_INTEGER FileOffset,
                  IN ULONG Length,
                  OUT PMDL *MdlChain,
                  OUT PIO_STATUS_BLOCK IoStatus)
{
	PVOID VirtualAddress = nullptr;
	LONG ZeroFlags = NULL;
	ULONG LENGTH_FINAL = Length;
	PVOID VirtualAddress = nullptr;
	PVACB VACB  = nullptr;
	ULONG ReceivedLength;
	ULONG Information;
	PMDL Allocated;
	LARGE_INTEGER FOffset = FileOffset;
	PSHARED_CACHE_MAP sharedcachmap = FileObject->SectionObjectPointer->SharedCacheMap; 
	PVOID VirtualAddress = nullptr;
	PMDL MDLBuffer;
	PMDL MDLNext; 
	LARGE_INTEGER Offset_Lenghth;

	
	/* Note Read Ahead Flags are not implemented but are undocumented & rarely used */ 
if ( (FileObject->Flags & 0x10) == 0 )
{
    if ( IoIsFileOriginRemote(FileObject) && !CcCanIWriteStream(FileObject, Length, 0, 0) )
      RtlRaiseStatus(-1073741670);
}
	__try
{
/* Iterate until it is final length is null*/ 	
	while(Length != NULL)
	{
		
		VirtualAddress = static_cast<void*>(CcGetVirtualAddress(sharedcachmap, &VACB, FOffset,(LARGE_INTEGER)&ReceivedLength, 0));
		ZeroFlags = 2 ; // Middle Flags are Zero
		if ((FileOffset->LowPart & 4095) == 0 && ReceivedLength >= 4096  )
		{ 
	         ZeroFlags = 3;
		}
	  LARGE_INTEGER Offset_Lenghth =  FOffset.QuadPart +  static_cast<LONGLONG>(ReceivedLength);

	
	/* Should not exceed PageLimit */
		
		if ( ReceivedLength >= 4096  ) 
		{   
			ReceivedLength = Length;
		}
		if((Offset_Lenghth->LowPart & 4095) = 0)
		{
			ZeroFlags |= 4;
		}
		
	 KeAcquireGuardedMutex(&sharedcachmap->BcbLock);
	
		/* Allocate the MDL ,it is not associated with Specific IRP*/
		Allocated = IoAllocateMdl(VirtualAddress,ReceivedLength , false, false, optional_irp);
		
		/* Assign the MDL to MmProbeAndLockPages to prevent Page Fault/ Data Corruption */
		MmProbeAndLockPages(Allocated, KernelMode, IoWriteAccess);
		
	 KeReleaseGuardedMutex(&sharedcachmap->BcbLock);
		/* Free the VACB */
		CcFreeVirtualAddress(VACB);
		
		/* Now Update the MDL Chain with allocated one */
		MDLNext = *MdlChain;
/* Check if Valid MDL Chain already exist, if so update it with allocated one else assign MDL Chain with one we allocated  */
   if ( *MdlChain != NULL)
    {
      while ( MDLNext->Next )
        MDLNext = MDLNext->Next;
      MDLNext->Next = Allocated;
    }
	else
    {
      *MdlChain = Allocated;
    }
		
	}
	
	FOffset.QuadPart = Offset_Lenghth.QuadPart;
	
	/* Update the IOSTATUS Information FLag with amount of Byte Counts */
	Information += ReceivedLength;
	/* Adjust the length , else you will be in mess of a infinite nonsensical loop fighting with Exception Handler */ 
	Length -= ReceivedLength;
	
	
	
}
	
__finally {
	/* No matter what , even in face of World War Z, OpenCount HISTORY must be updated & along with bytes elapsed by IRQL */ 
  IoStatus->Status = false;
  IoStatus->Information = Information ;
  KIRQL SpinLock = KeAcquireQueuedSpinLock(LockQueueMasterLock);
  InterlockedIncrement(SharedCacheMap->OpenCount);
  KeReleaseQueuedSpinLock(LockQueueMasterLock, SpinLock);


}
}

VOID
NTAPI
CcMdlRead (
    IN PFILE_OBJECT FileObject,
    IN PLARGE_INTEGER FileOffset,
    IN ULONG Length,
    OUT PMDL * MdlChain,
    OUT PIO_STATUS_BLOCK IoStatus)
{
		
	ULONG LENGTH_FINAL = Length;
	PVOID VirtualAddress = nullptr;
	PVACB VACB  = nullptr;
	ULONG ReceivedLength;
	ULONG Information;
	PMDL Allocated;
	LARGE_INTEGER FOffset = FileOffset;
	PSHARED_CACHE_MAP sharedcachmap = FileObject->SectionObjectPointer->SharedCacheMap; 
	PVOID VirtualAddress = nullptr;
	PMDL MDLBuffer;
	PMDL MDLNext; 
	LARGE_INTEGER Offset_Lenghth;
__try
{
/* Iterate until it is final length is null*/ 	
	while(Length != NULL)
	{
		
		VirtualAddress = static_cast<void*>(CcGetVirtualAddress(sharedcachmap, &VACB, FOffset,(LARGE_INTEGER)&ReceivedLength, 0));
		INT PagePriority = static_cast<int>(((&sharedcachmap->NodeTypeCode >> 18) & 7));
		
		if ((sharedcachmap->Flags & 8)== null )
		{
			CcFetchDataForRead(FileObject,&FOffset,Length,Wait_Type_MDL_Read,&FaultedData,&VACB,PagePriority,MDL_READTYPE_DiskIoAttribution);
		}
		
		if ( ReceivedLength > Length )
		{   
			ReceivedLength = Length;
		}
	
	  Offset_Lenghth =  FOffset.QuadPart +  static_cast<LONGLONG>(ReceivedLength);
		
	
		/* Allocate the MDL ,it is not associated with Specific IRP*/
		Allocated = IoAllocateMdl(VirtualAddress,ReceivedLength , false, false, optional_irp);
		
		/* Assign the MDL to MmProbeAndLockPages to prevent Page Fault/ Data Corruption */
		MmProbeAndLockPages(Allocated, KernelMode, IoReadAccess);
		/* Free the VACB */
		CcFreeVirtualAddress(VACB);
		
		/* Now Update the MDL Chain with allocated one */
		MDLNext = *MdlChain;
/* Check if Valid MDL Chain already exist, if so update it with allocated one else assign MDL Chain with one we allocated  */
   if ( *MdlChain != NULL)
    {
      while ( MDLNext->Next )
        MDLNext = MDLNext->Next;
      MDLNext->Next = Allocated;
    }
	else
    {
      *MdlChain = Allocated;
    }
		
	}
	
	FOffset.QuadPart = Offset_Lenghth.QuadPart;
	
	/* Update the IOSTATUS Information FLag */
	Information += ReceivedLength;
	/* Adjust the length , else you will be in mess of a infinite nonsensical loop fighting with Exception Handler */ 
	Length -= ReceivedLength;
	
	
	
}
	
__finally {
	
 if ( (&sharedcachmap->NodeTypeCode & 0x20000) == 0 && FaultedData )
 {
    CcScheduleReadAhead(FileObject, FileOffset,Length);
   
 }

  
/* No mater What , Catch History must be updated even if Aliens Invasion Happens that day*/
/* UPDATE CATCH HISTORY */
InterlockedExchange64(&PrivateCachemap->FileOffset1,PrivateCachemap->FileOffset2);
InterlockedExchange64(&PrivateCachemap->BeyondLastByte1,PrivateCachemap->BeyondLastByte2);
InterlockedExchange64(&PrivateCachemap->FileOffset2,*FileOffset);
LONG LONG FinalLength =FileOffset->QuadPart+ static_cast<LONGLONG>(Length);
InterlockedExchange64(&PrivateCachemap->BeyondLastByte2.Quadpart,FinalLength);
/* Update IRP Bytes */ 
IoStatus->Status = false;
IoStatus->Information = Information;
}
}




